package com.sdk.springbootadvancedsearch.util;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.sdk.springbootadvancedsearch.domain.request.FilterCondition;
import com.sdk.springbootadvancedsearch.domain.request.QueryRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.lang.reflect.Array;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

@Component
@Slf4j
public class DynamicQueryBuilder {
    // 操作符映射
    private static final Map<String, BiConsumer<QueryWrapper<?>, ConditionContext>> OPERATOR_MAP = new HashMap<>();

    static {
        // 初始化操作符映射
        OPERATOR_MAP.put("eq", (wrapper, ctx) -> wrapper.eq(ctx.column, ctx.value));
        OPERATOR_MAP.put("like", (wrapper, ctx) -> wrapper.like(ctx.column, ctx.value));
        OPERATOR_MAP.put("in", (wrapper, ctx) -> {
            if (ctx.value instanceof Collection) {
                wrapper.in(ctx.column, (Collection<?>) ctx.value);
            }
        });
        OPERATOR_MAP.put("gt", (wrapper, ctx) -> wrapper.gt(ctx.column, ctx.value));
        OPERATOR_MAP.put("gte", (wrapper, ctx) -> wrapper.ge(ctx.column, ctx.value));
        OPERATOR_MAP.put("lt", (wrapper, ctx) -> wrapper.lt(ctx.column, ctx.value));
        OPERATOR_MAP.put("lte", (wrapper, ctx) -> wrapper.le(ctx.column, ctx.value));
        OPERATOR_MAP.put("between", (wrapper, ctx) -> {
            if (ctx.value instanceof Object[] && ((Object[]) ctx.value).length == 2) {
                Object[] range = (Object[]) ctx.value;
                wrapper.between(ctx.column, range[0], range[1]);
            }
        });
    }

    // 条件上下文
    private static class ConditionContext {
        String column;
        Object value;
    }

    public <T> QueryWrapper<T> buildFilters(QueryRequest request) {
        List<FilterCondition> filters = request.getFilters();
        String logicMode = request.getLogicMode();
        List<String> selectFields = request.getSelectFields();

        QueryWrapper<T> wrapper = new QueryWrapper<>();

        // ===== 新增字段选择逻辑 =====
        if (selectFields != null && !selectFields.isEmpty()) {
            String[] array = selectFields.stream()
                    .filter(StringUtils::isNotBlank)
                    .map(StringUtils::camelToUnderline).toArray(String[]::new);
            if(array.length > 0){
                wrapper.select(array);
            }
        }

        if (filters == null || filters.isEmpty()) {
            return wrapper;
        }

        boolean isOrMode = "or".equalsIgnoreCase(logicMode);

        for (FilterCondition filter : filters) {
            try {
                // 1. 安全校验
                validateFilter(filter);

                // 2. 创建上下文
                ConditionContext ctx = new ConditionContext();
                ctx.column = StringUtils.camelToUnderline(filter.getKey());
                ctx.value = processValue(filter);

                // 3. 获取操作符处理器
                BiConsumer<QueryWrapper<?>, ConditionContext> handler =
                        OPERATOR_MAP.get(filter.getMode().toLowerCase());

                if (handler == null) {
                    throw new UnsupportedOperationException("不支持的查询模式: " + filter.getMode());
                }

                // 4. 应用查询条件
                if (isOrMode) {
                    wrapper.or(w -> handler.accept(w, ctx));
                } else {
                    handler.accept(wrapper, ctx);
                }
            } catch (Exception e) {
                log.error("构建查询条件失败: filter={}, error={}", filter, e.getMessage());
                throw new RuntimeException("查询条件构建失败: " + filter.getKey(), e);
            }
        }

        return wrapper;
    }

    private void validateFilter(FilterCondition filter) {
        Object value = filter.getValue();
        // 特殊模式的值校验
        if ("in".equalsIgnoreCase(filter.getMode())) {
            if (value instanceof Collection && ((Collection<?>) value).isEmpty()) {
                throw new IllegalArgumentException("in模式需要最少一个值");
            }

            // 如果是数组类型
            if (value.getClass().isArray() && Array.getLength(value) == 0) {
                throw new IllegalArgumentException("in模式需要最少一个值");
            }

            // 处理字符串类型的逗号分隔值
            if (value instanceof String && ((String) value).split(",").length == 0) {
                throw new IllegalArgumentException("in模式需要最少一个值");
            }
        }
        if ("between".equalsIgnoreCase(filter.getMode())) {
            if (!(value instanceof Object[]) ||
                    ((Object[]) value).length != 2) {
                throw new IllegalArgumentException("between模式需要两个值的数组");
            }
        }
    }

    private Object processValue(FilterCondition filter) {
        Object value = filter.getValue();
        String type = filter.getType().toLowerCase();
        String mode = filter.getMode().toLowerCase();

        // 统一处理IN模式的值
        if ("in".equals(mode)) {
            return processInValue(value, type);
        }

        // 类型转换
        return convertValue(value, type);
    }

    private Object processInValue(Object value, String type) {
        // 如果已经是集合类型，直接转换
        if (value instanceof Collection) {
            return convertCollection((Collection<?>) value, type);
        }

        // 如果是数组类型
        if (value != null && value.getClass().isArray()) {
            return convertArray(value, type);
        }

        // 处理字符串类型的逗号分隔值
        if (value instanceof String) {
            String[] parts = ((String) value).split(",");
            return convertArray(parts, type);
        }

        throw new IllegalArgumentException("IN模式的值必须是数组或逗号分隔字符串");
    }

    private Object convertValue(Object value, String type) {
        if (value == null) return null;

        try {
            switch (type) {
                case "number":
                    if (value instanceof Number) return value;
                    return Double.parseDouble(value.toString());

                case "date":
                    if (value instanceof Date) return value;
                    if (value instanceof String) {
                        return LocalDateTime.parse((String) value);
                    }
                    throw new IllegalArgumentException("日期类型必须是字符串或Date对象");

                case "boolean":
                    if (value instanceof Boolean) return value;
                    return Boolean.parseBoolean(value.toString());

                default: // string
                    return value.toString();
            }
        } catch (Exception e) {
            throw new RuntimeException("类型转换失败: value=" + value + ", type=" + type, e);
        }
    }

    private List<Object> convertCollection(Collection<?> values, String type) {
        return values.stream()
                .map(v -> convertValue(v, type))
                .collect(Collectors.toList());
    }

    private List<Object> convertArray(Object array, String type) {
        int length = Array.getLength(array);
        List<Object> result = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            result.add(convertValue(Array.get(array, i), type));
        }
        return result;
    }
}
